Editor.Shape = function (i, u) {
	this.dx;
	this.dy;
	this.inix;
	this.iniy;
	this.iniPosx;
	this.iniPosy;
	this.figure;
	this.figureBack;
	this.figureText;
	this.figureSet;

	this.impl = i;

	this.bbox = new Editor.Models.BBox();
	this.bbox.init();

	this.draggerResize = new Editor.Draggers.Resize();
	this.draggerResize.init(this);

	this.deckClose = new Editor.Decks.Close();
	this.deckClose.init(this);

	this.deckSelect = new Editor.Decks.Select();
	this.deckSelect.init(this);

	if (u == undefined) {
		this.uuid = Math.uuid();
	} else {
		this.uuid = u;
	}

	this.minWidth = 0;
	this.minHeight = 0;

	this.isActive = false;
	this.isSelected = false;
	this.isDeleted = false;
}

Editor.Shape.prototype.unselect = function () {
	if (this.isSelected) {
		Editor.Util.unselect(this);
		this.deckSelect.remove();
		this.isSelected = false;
	}
}

Editor.Shape.prototype.select = function () {
	this.deckSelect.draw();
	this.isSelected = true;
}

Editor.Shape.prototype._remove = function () {
	if (this.isSelected) this.impl.unselect();
	this.figureBack.remove();
	this.figureText.remove();
	this.figure.remove();
	delete this.figureBack;
	delete this.figureText;
	delete this.figure;
	this.deckClose.remove();
	this.draggerResize.remove();
	this.isDeleted = true;
}

Editor.Shape.prototype.remove = function () {
	this._remove();
}

Editor.Shape.prototype.mouseover = function () {
	if (!Editor.Util.isDragging()) {
		this.figure.attr(Editor.CONFIG.SHAPE_ATTR_MOUSEOVER);
		this.draggerResize.mouseover();
		this.deckClose.mouseover();
	}
}

Editor.Shape.prototype.mouseout = function () {
	if (!Editor.Util.isDragging()) {
		this.figure.attr(this.impl.getShapeAttr());
		this.draggerResize.mouseout();
		this.deckClose.mouseout();
	}
}

Editor.Shape.prototype.click = function () {
	this.impl.toFront();
}

Editor.Shape.prototype.toFront = function () {
	this.figureBack.toFront();
	this.figureText.toFront();
	this.figure.toFront();
	this.draggerResize.toFront();
	this.deckClose.toFront();
}

Editor.Shape.prototype.draw = function () {
	this.isDeleted = false;

	this.figureBack = this.impl.getFigure();
	this.figureBack.attr(Editor.CONFIG.SHAPE_ATTR_BACKGROUND);

	if (this.impl.alignTextVertical && this.impl.alignTextVertical == 'top') {
		this.figureText = Editor.STATE.CANVAS.text(this.bbox.getX() + this.bbox.getWidth() / 2, this.bbox.getY() + 10, this.impl.getText());
	} else {
		this.figureText = Editor.STATE.CANVAS.text(this.bbox.getX() + this.bbox.getWidth() / 2, this.bbox.getY() + this.bbox.getHeight() / 2, this.impl.getText());
	}

	this.figureText.attr(this.impl.getTextAttr());

	this.figure = this.impl.getFigure();

	this.figureSet = Editor.STATE.CANVAS.set();
	this.figureSet.push(this.figureBack);
	this.figureSet.push(this.figure);

	this.figure.mouseover(this.impl.mouseover);
	this.figure.mouseout(this.impl.mouseout);
	this.figure.mousedown(this.impl.mousedown);

	this.figure.click(this.impl.click);
	this.figure.impl = this.impl;

	this.draggerResize.draw();
	this.draggerResize.redraw();

	this.deckClose.draw();
	this.deckClose.redraw();
}

Editor.Shape.prototype.moveTo = function (newX, newY) {
	//console.log("move to : " + newX + "," + newY);
	var deltaX = newX - this.bbox.getX();
	var deltaY = newY - this.bbox.getY();
	if (this.figure) {
		this.impl.translate(deltaX, deltaY);
	}
}

Editor.Shape.prototype.updateText = function () {
	this.figureText.attr({
		text: this.impl.getText(),
		x: this.bbox.getX() + this.bbox.getWidth() / 2,
	});
	if (this.impl.alignTextVertical && this.impl.alignTextVertical == 'top') {
		//na
	} else {
		this.figureText.attr({
			y: this.bbox.getY() + this.bbox.getHeight() / 2
		});
	}

	var tw = this.figureText.getBBox().width + Editor.CONFIG.SHAPE_TEXT_DELTA_X;
	var th = this.figureText.getBBox().height + Editor.CONFIG.SHAPE_TEXT_DELTA_Y;
	var dw = tw;
	var dh = th;
	if (Editor.CONFIG.GRID_SNAP) {
		dw = Math.round(dw / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
		dh = Math.round(dh / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
		if (tw > dw) {
			dw += Editor.CONFIG.GRID_SIZE;
		}
		if (th > dh) {
			dh += Editor.CONFIG.GRID_SIZE;
		}
	}
	this.minWidth = dw;
	this.minHeight = dh;
	var deltaw = dw - this.bbox.getWidth();
	var deltah = dh - this.bbox.getHeight();
	if (deltaw < 0) {
		deltaw = 0;
	}
	if (deltah < 0) {
		deltah = 0;
	}
	this.impl._resize(deltaw, deltah);
}

Editor.Shape.prototype.getMinWidth = function () {
	if (this.minWidth == 0) {
		this.impl.updateText;
	}
	return this.minWidth;
}

Editor.Shape.prototype.getMinHeight = function () {
	if (this.minHeight == 0) {
		this.impl.updateText();
	}
	return this.minHeight;
}

Editor.Shape.prototype._resize = function (dw, dh) {
	//console.log("_resize : " + dw + "," + dh);
	if (dw != 0 || dh != 0) {
		this.bbox.setWidth(this.bbox.getWidth() + dw);
		this.bbox.setHeight(this.bbox.getHeight() + dh);
		if (this.figure) {
			var stateSelect = this.isSelected;
			if (stateSelect) {
				this.impl.unselect();
			}
			this.figureSet.attr({
				width: this.bbox.getWidth(),
				height: this.bbox.getHeight()
			});
			if (this.impl.alignTextVertical && this.impl.alignTextVertical == 'top') {
				//na
				this.figureText.attr({
					x: this.bbox.getX() + this.bbox.getWidth() / 2,
				});
			} else {
				this.figureText.attr({
					x: this.bbox.getX() + this.bbox.getWidth() / 2,
					y: this.bbox.getY() + this.bbox.getHeight() / 2
				});
			}
			this.draggerResize.translate(dw, dh);
			this.deckClose.translate(dw, 0);
			if (stateSelect) {
				Editor.Util.select(this.impl);
			}
		}
	}
}

Editor.Shape.prototype.resize = function (dw, dh) {
	//console.log("resize : " + dw + "," + dh);
	if (dw != 0 || dh != 0) {
		var impl = this.impl;
		var cmd = new JS.Command({
			execute: function () {
				impl._resize(dw, dh);
				Editor.Util.showAllLines();
			},
			undo: function () {
				impl._resize(-dw, -dh);
				Editor.Util.showAllLines();
			},
			stack: Editor.STATE.CMDSTACK
		});
		cmd.name = 'resize shape';
		cmd.execute();
		Editor.Util.showAllLines();
	}
}

Editor.Shape.prototype.frameResize = function () {
	return Editor.STATE.CANVAS.rect(this.bbox.getX(), this.bbox.getY(), this.bbox.getWidth(), this.bbox.getHeight(), 0).
	attr(Editor.CONFIG.SHAPE_FRAMERESIZE_ATTR);
}

Editor.Shape.prototype.saveIni = function (e) {
	this.inix = e.clientX;
	this.iniy = e.clientY;
	this.iniPosx = this.bbox.getX();
	this.iniPosy = this.bbox.getY();
}

Editor.Shape.prototype.mousedown = function (e) {
	if (!Editor.Util.isDragging()) {
		this.impl.mouseout();
		Editor.Util.hideAllLines();
		this.dx = e.clientX;
		this.dy = e.clientY;

		this.saveIni(e);
		Editor.STATE.DRAGGER = this;
		
		this.impl.toFront();

		Editor.STATE.BACKGROUNDTEMP=Editor.STATE.BACKGROUND.clone();
		Editor.STATE.BACKGROUNDTEMP.toFront();

		this.isActive = true;

		var arrSelected = Editor.STATE.SELECTED;
		if (arrSelected.length > 0) {
			var tempIsSelected = false;
			for (var i = 0; i < arrSelected.length; i++) {
				if (arrSelected[i].getUuid() == this.getUuid()) {
					tempIsSelected = true;
				}
			}
			if (!tempIsSelected) {
				Editor.Util.unselectAll();
			} else {
				for (var i = 0; i < arrSelected.length; i++) {
					arrSelected[i].saveIni(e);
				}
			}
		}
	}
}

Editor.Shape.prototype.onmousemove = function (e) {
	var dX = e.clientX - this.dx;
	var dY = e.clientY - this.dy;
	this.dx += dX;
	this.dy += dY;

	var arrSelected = Editor.STATE.SELECTED;
	if (arrSelected.length > 0) {
		for (var i = 0; i < arrSelected.length; i++) {
			arrSelected[i].translate(dX, dY);
		}
	} else {
		this.impl.translate(dX, dY);
	}
}

Editor.Shape.prototype.onmouseup = function () {
	var finalX = this.bbox.getX();
	var finalY = this.bbox.getY();
	if (Editor.CONFIG.GRID_SNAP) {
		finalX = Math.round(finalX / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
		finalY = Math.round(finalY / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
	}

	var arrSelected = Editor.STATE.SELECTED;
	if (arrSelected.length > 0) {
		var traX = finalX - this.iniPosx;
		var traY = finalY - this.iniPosy;

		var arr = new Array();
		var arrInix = new Array();
		var arrIniy = new Array();
		for (var i = 0; i < arrSelected.length; i++) {
			arr.push(arrSelected[i]);
			arrInix.push(arrSelected[i].getIniPosx());
			arrIniy.push(arrSelected[i].getIniPosy());
		}
		var cmd = new JS.Command({
			execute: function () {
				for (var i = 0; i < arr.length; i++) {
					arr[i].moveTo(arrInix[i] + traX, arrIniy[i] + traY);
				}
				Editor.Util.showAllLines();
			},
			undo: function () {
				for (var i = 0; i < arr.length; i++) {
					arr[i].moveTo(arrInix[i], arrIniy[i]);
				}
				Editor.Util.showAllLines();
			},
			stack: Editor.STATE.CMDSTACK
		});
		cmd.name = 'move shapes';
		cmd.execute();
	} else {
		if (finalX != this.iniPosx || finalY != this.iniPosy) {
			var iposx = this.iniPosx;
			var iposy = this.iniPosy;
			var impl = this.impl;
			cmd = new JS.Command({
				execute: function () {
					impl.moveTo(finalX, finalY);
					Editor.Util.showAllLines();
				},
				undo: function () {
					impl.moveTo(iposx, iposy);
					Editor.Util.showAllLines();
				},
				stack: Editor.STATE.CMDSTACK
			});
			cmd.name = 'move shape';
			cmd.execute();
		} else {
			this.impl.moveTo(this.iniPosx, this.iniPosy);
		}
	}


	Editor.STATE.BACKGROUNDTEMP.remove();
	delete Editor.STATE.BACKGROUNDTEMP;

	this.isActive = false;
	Editor.STATE.DRAGGER = undefined;
	Editor.Util.showAllLines();
}

Editor.Shape.prototype._translate = function (deltaX, deltaY) {
	//console.log("_translate : " + deltaX + "," + deltaY);
	this.figureSet.translate(deltaX, deltaY);
	this.figureText.translate(deltaX, deltaY);
	this.draggerResize.translate(deltaX, deltaY);
	if (this.isSelected) {
		this.deckSelect.translate(deltaX, deltaY);
	}
	this.deckClose.translate(deltaX, deltaY);
	this.bbox.setX(this.bbox.getX() + deltaX);
	this.bbox.setY(this.bbox.getY() + deltaY);
}

Editor.Shape.prototype.translate = function (deltaX, deltaY) {
	//console.log("translate : " + deltaX + "," + deltaY);
	this._translate(deltaX, deltaY);
}

Editor.Shape.prototype.animateRotate360 = function() {
	this.figureBack.animate({rotation: "360"}, 1000);
}

Editor.Shape.prototype.animateFillColor = function(newColor) {
	this.figureBack.animate({fill: newColor}, 1000, this.animateFillDescolor);
}

Editor.Shape.prototype.animateFillDescolor = function() {
	this.animate({fill: "#fff"}, 1000);
}

Editor.Shape.prototype.getUuid = function () {
	return this.uuid;
}

Editor.Shape.prototype.getIsActive = function () {
	return this.isActive;
}

Editor.Shape.prototype.getIsDeleted = function () {
	return this.isDeleted;
}

Editor.Shape.prototype.setX = function (newX) {
	this.bbox.setX(newX);
}

Editor.Shape.prototype.getX = function () {
	return this.bbox.getX();
}

Editor.Shape.prototype.setY = function (newY) {
	this.bbox.setY(newX);
}

Editor.Shape.prototype.getY = function () {
	return this.bbox.getY();
}

Editor.Shape.prototype.setWidth = function (newWidth) {
	this.bbox.setWidth(newWidth);
}

Editor.Shape.prototype.getWidth = function () {
	return this.bbox.getWidth();
}

Editor.Shape.prototype.setHeight = function (newHeight) {
	this.bbox.setHeight(newHeight);
}

Editor.Shape.prototype.getHeight = function () {
	return this.bbox.getHeight();
}

Editor.Shape.prototype.toString = function () {
	return 'Shape-->(' + 'uuid: ' + this.uuid + ' ; ' + this.bbox.toString() + ')'
}

Editor.Shape.prototype.getDraggerResize = function () {
	return this.draggerResize;
}

Editor.Shape.prototype.getDeckClose = function () {
	return this.deckClose;
}

Editor.Shape.prototype.getImplementation = function () {
	return this.impl;
}

Editor.Shape.prototype.getIniPosx = function () {
	return this.iniPosx;
}

Editor.Shape.prototype.getIniPosy = function () {
	return this.iniPosy;
}

Editor.Shape.prototype.toObject = function () {
	return {
		'bbox': this.bbox.toObject(),
		'uuid': this.uuid
	}
}
